#include "ASTextView.h"
#include "..\base\ASStdLib.h"

#define STEP_OFFSET 16

static as_ret as_ctrl_textview_change_text(as_control* ctrl_p, ASWSTR text)
{
    as_textview* tv_p = (as_textview*)ctrl_p;

    if(!tv_p || !text)
        return AS_INVALID_PARAM;

    tv_p->label->change_text((as_control*)tv_p->label, text);
    tv_p->text_total_height = tv_p->label->get_total_height((as_control*)tv_p->label);
    return AS_OK;
}

static as_ret as_ctrl_textview_set_text_color(as_control* ctrl_p, ASUINT color)
{
    as_textview* tv_p = (as_textview*)ctrl_p;

    if(!tv_p)
        return AS_INVALID_PARAM;

    return tv_p->label->set_text_color((as_control*)tv_p->label, color);
}

static as_ret as_ctrl_textview_set_bg_color(as_control* ctrl_p, ASUINT color)
{
    as_textview* tv_p = (as_textview*)ctrl_p;

    if(!tv_p)
        return AS_INVALID_PARAM;

    return tv_p->label->set_bg_color((as_control*)tv_p->label, color);
}

static as_ret as_ctrl_textview_set_bg_frame_color(as_control* ctrl_p, ASUINT color)
{
    as_textview* tv_p = (as_textview*)ctrl_p;

    if(!tv_p)
        return AS_INVALID_PARAM;

    return tv_p->label->set_bg_frame_color((as_control*)tv_p->label, color);
}

static void as_ctrl_textview_paint(as_control* ctrl_p)
{
    as_textview* tv_p = (as_textview*)ctrl_p;

    if(!tv_p->label || tv_p->base.get_hidden((as_control*)tv_p))
        return;

    tv_p->label->base.paint_hdlr((as_control*)tv_p->label);

    //scroll bar
    if(tv_p->sb && tv_p->if_show_scrollbar)
    {
        tv_p->sb->base.paint_hdlr((as_control*)tv_p->sb);
    }
}

static as_ret as_ctrl_textview_pen_hdlr(as_control* ctrl_p, ASINT event, ASINT x, ASINT y)
{
    as_textview* tv_p = (as_textview*)ctrl_p;

    if(!tv_p)
        return AS_INVALID_PARAM;

    if(tv_p->text_total_height <= tv_p->base.area.h)
        return AS_IGNORE;

    if(event == AS_EVT_TOUCH_DOWN)
    {
        if(tv_p->is_taped == FALSE && AS_POINT_IN_RECT(x, y, tv_p->base.area))
        {
            tv_p->is_taped = TRUE;
            tv_p->is_moved = FALSE;
            tv_p->last_pos.x = (ASINT16)x;
            tv_p->last_pos.y = (ASINT16)y;
            return AS_OK;
        }
        else
            return AS_IGNORE;
    }
    else if(event == AS_EVT_TOUCH_MOVE && tv_p->is_taped == TRUE)
    {
        ASINT y_off;
        tv_p->is_moved = TRUE;
        y_off = tv_p->label->text_y_off + y - tv_p->last_pos.y;

        if(y_off > 0)
            y_off = 0;

        if(y_off < tv_p->base.area.h - tv_p->text_total_height)
            y_off = tv_p->base.area.h - tv_p->text_total_height;

        tv_p->label->set_text_offset((as_control*)tv_p->label, tv_p->label->text_x_off, y_off);

        if(tv_p->sb)
        {
            tv_p->sb->set_value((as_control*)tv_p->sb, -y_off, tv_p->base.area.h,
                                tv_p->text_total_height + y_off - tv_p->base.area.h);
        }

        tv_p->base.paint_hdlr((as_control*)tv_p);
        as_ctrl_flush();
        tv_p->last_pos.x = (ASINT16)x;
        tv_p->last_pos.y = (ASINT16)y;
        return AS_OK;
    }
    else if(event == AS_EVT_TOUCH_UP && tv_p->is_taped == TRUE)
    {
        tv_p->is_taped = FALSE;
        tv_p->is_moved = FALSE;
        return AS_OK;
    }
    else
        return AS_IGNORE;
}

static as_ret as_ctrl_textview_key_hdlr(as_control* ctrl_p, ASINT event, ASINT keycode)
{
    as_textview* tv_p = (as_textview*)ctrl_p;

    if(!tv_p)
        return AS_INVALID_PARAM;

    if(ctrl_p->if_hidden)
        return AS_IGNORE;

    if(tv_p->text_total_height <= tv_p->base.area.h)
        return AS_IGNORE;

    if(keycode == AS_KEY_DOWN && event == AS_EVT_KEY_DOWN)
    {
        ASINT y_off = tv_p->label->text_y_off - (tv_p->base.area.h / 2);

        if(y_off < tv_p->base.area.h - tv_p->text_total_height)
        {
            y_off = tv_p->base.area.h - tv_p->text_total_height;
        }

        tv_p->label->set_text_offset((as_control*)tv_p->label, tv_p->label->text_x_off, y_off);

        if(tv_p->sb)
        {
            tv_p->sb->set_value((as_control*)tv_p->sb, -y_off, tv_p->base.area.h,
                                tv_p->text_total_height + y_off - tv_p->base.area.h);
        }

        tv_p->base.paint_hdlr((as_control*)tv_p);
        as_ctrl_flush();
        return AS_OK;
    }
    else if(keycode == AS_KEY_UP && event == AS_EVT_KEY_DOWN)
    {
        ASINT y_off = tv_p->label->text_y_off + (tv_p->base.area.h / 2);

        if(y_off > 0)
        {
            y_off = 0;
        }

        tv_p->label->set_text_offset((as_control*)tv_p->label, tv_p->label->text_x_off, y_off);

        if(tv_p->sb)
        {
            tv_p->sb->set_value((as_control*)tv_p->sb, -y_off, tv_p->base.area.h,
                                tv_p->text_total_height - (-y_off) - tv_p->base.area.h);
        }

        tv_p->base.paint_hdlr((as_control*)tv_p);
        as_ctrl_flush();
        return AS_OK;
    }
    else
    {
        return AS_IGNORE;
    }
}

static void as_ctrl_textview_set_hidden(as_control* ctrl_p, ASBOOL if_hidden)
{
    as_textview* tv_p = (as_textview*)ctrl_p;

    if(!tv_p || tv_p->base.if_hidden == if_hidden)
        return;

    tv_p->base.if_hidden = if_hidden;
    tv_p->label->base.set_hidden((as_control*)tv_p->label, if_hidden);
}

static as_ret as_ctrl_textview_set_if_small(as_control* ctrl_p, ASBOOL if_small)
{
    as_textview* tv_p = (as_textview*)ctrl_p;

    if(!tv_p || !tv_p->label || tv_p->label->if_small == if_small)
        return AS_INVALID_PARAM;

    tv_p->label->set_if_small((as_control*)tv_p->label, if_small);
    tv_p->text_total_height = tv_p->label->get_total_height((as_control*)tv_p->label);

    if(tv_p->sb)
    {
        tv_p->sb->set_value((as_control*)tv_p->sb, tv_p->label->text_y_off, tv_p->label->base.area.h,
                            tv_p->text_total_height - tv_p->label->text_y_off - tv_p->label->base.area.h);
    }

    return AS_OK;
}

static as_ret as_ctrl_textview_set_sb_show(as_control* ctrl_p, ASBOOL if_show)
{
    as_textview* tv_p = (as_textview*)ctrl_p;

    if(!tv_p || tv_p->if_show_scrollbar == if_show)
        return AS_INVALID_PARAM;

    tv_p->if_show_scrollbar = if_show;
    return AS_OK;
}

as_textview* as_ctrl_textview_create(as_rect area, ASWSTR text)
{
    as_textview* tv_p = ASNULL;
    ASINT len;

    if(!text)
    {
        return ASNULL;
    }

    len = as_wstrlen(text);

    if(len < 0)
        return ASNULL;

    tv_p = as_calloc(sizeof(as_textview));

    if(!tv_p)
        return ASNULL;

    tv_p->label = as_ctrl_label_create(area, text);

    if(!tv_p->label)
    {
        as_free(tv_p);
        return ASNULL;
    }

    tv_p->label->set_layout((as_control*)tv_p->label, AS_LABEL_TEXT_LEFT_TOP);
    tv_p->text_total_height = tv_p->label->get_total_height((as_control*)tv_p->label);
    {
        as_rect sb_area;
        as_memcpy(&sb_area, &area, sizeof(as_rect));
        sb_area.w = 4;
        sb_area.x = area.x + area.w - sb_area.w;
        tv_p->sb = as_ctrl_scrollbar_create(sb_area, AS_SCROLLBAR_VERTICAL);

        if(!tv_p->sb)
        {
            as_ctrl_destroy((as_control*)tv_p->label);
            as_free(tv_p);
            return ASNULL;
        }
        else
        {
            tv_p->sb->set_value((as_control*)tv_p->sb, tv_p->label->text_y_off, tv_p->label->base.area.h,
                                tv_p->text_total_height - tv_p->label->text_y_off - tv_p->label->base.area.h);
        }
    }
    as_ctrl_init((as_control*)tv_p, area);
    tv_p->base.paint_hdlr = as_ctrl_textview_paint;
    tv_p->base.set_hidden = as_ctrl_textview_set_hidden;
    tv_p->base.pen_hdlr = as_ctrl_textview_pen_hdlr;
    tv_p->base.key_hdlr = as_ctrl_textview_key_hdlr;
    tv_p->base.ctrl_type = AS_CTRL_TEXTVIEW;
    tv_p->change_text = as_ctrl_textview_change_text;
    tv_p->set_bg_color = as_ctrl_textview_set_bg_color;
    tv_p->set_text_color = as_ctrl_textview_set_text_color;
    tv_p->set_bg_frame_color = as_ctrl_textview_set_bg_frame_color;
    tv_p->set_sb_show = as_ctrl_textview_set_sb_show;
    tv_p->set_if_small = as_ctrl_textview_set_if_small;
    return tv_p;
}

as_ret as_ctrl_textview_destroy(as_textview* ctrl_textview_p)
{
    if(!ctrl_textview_p)
        return AS_INVALID_PARAM;

    if(ctrl_textview_p->label)
    {
        as_ctrl_destroy((as_control*)ctrl_textview_p->label);
    }

    as_free(ctrl_textview_p);
    return AS_OK;
}